#ifndef __vos_section__
#define __vos_section__

#include <set>
#include "ram.h"
#include "pgtx64.h"
#include "imagex.h"
#include "directory.h"
#include "kfile.h"

namespace xm
{
	class kernel_t;

	// file/protect/view
	enum 
	{
		DAC_READ	= 0x1,
		DAC_EXEC	= 0x2,
		DAC_WCOPY	= 0x4,
		DAC_WRITE	= 0x8,
		DAC_APPEND	= 0x10,
		DAC_ALL		= -1,
	};

	static uint32_t dac_to_paga( size_t acc )
	{
		if( !acc ) return PAGE_NOACCESS;
		uint32_t paga = 0;
		if( acc & DAC_READ )
			paga |= PGA_READ;
		if( acc & DAC_WRITE )
			paga |= PGA_WRITE;
		else if( acc & DAC_WCOPY )
			paga |= PGA_WCOPY;
		if( acc & DAC_EXEC )
			paga |= PGA_EXECUTE;
		return paga;
	}
	static uint32_t fma_to_paga( size_t acc )
	{
		if( !acc ) return PAGE_NOACCESS;
		uint32_t paga = 0;
		if( acc & FILE_MAP_READ )
			paga |= PGA_READ;
		if( acc & FILE_MAP_WRITE )
			paga |= PGA_WRITE;
		else if( acc & FILE_MAP_COPY )
			paga |= PGA_WCOPY;
		if( acc & FILE_MAP_EXECUTE )
			paga |= PGA_EXECUTE;
		return paga;
	}

	class section_t;

	struct section_user_t
	{
		virtual long on_section_invalid( section_t * sec, uint64_t offset ) = 0;
	};

	enum SectionType 
	{
		SectionUnknown,
		SectionData,
		SectionImage,
	};

	class section_t : public MountableObject<KoSection>, i_ram_owner_t, UnkBase
	{
	protected:
		struct sec_rmb_t : rmb_t
		{
			uint64_t offset;
		};

		typedef std::set<section_user_t*> users_t;

		enum { PAGE_WND = 4 * sizeof(size_t) };				// 32: 4*4*4, 64: 4*8*4

		sec_rmb_t			_wnd[PAGE_WND];
		uint64_t			_size;
		users_t				_users;
		uint64_t			_want_stand;

	public:

		iptr<IKernelObject>	ko;
		iptr<IKBStream>		data;

		UNKNOWN_IMP1( IKernelObject );

		section_t();

		SectionType get_type();

		uint64_t	required_base();

		uint64_t	get_size();

		long		create_image_section_w32( kernel_t& k, LPCSTR apathw32 );
		long		create_image_section( imagex_t * imgo );
		//long		create_file_section( volm_file_t * file, size_t acc, uint64_t size, LPCSTR aName );
		long		create_file_section( IKBStream * file, size_t acc, uint64_t size, LPCSTR aName );
		//////////////////////////////////////////////////////////////////////////

		long		get_page_paga( uint64_t offset, uint32_t * paga );
		rmb_t *		get_page_rmb( uint64_t offset );
		rmb_t*		get_ram_block( uint64_t offset, bool force = true );
		
		volm_file_t*get_data_file();
		imagex_t *	get_image();

	public:
		
		virtual void on_ram_block_invalid( rmb_t* pb );

		void insert_user( section_user_t* p );

		void remove_user( section_user_t* p );

	};

};


#endif